package org.demo.base.proxy;

import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.demo.base.proxy.cglibproxy.UserDao;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 静态代理总结:
 *      1.可以做到在不修改目标对象的功能前提下,对目标功能扩展.
 *      2.缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护
 * 动态代理总结:
 *      1.代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理
 * Cglib代理总结：
 *      静态代理和动态代理模式都是要求目标对象是实现一个接口的目标对象,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候就可以使用以目标对象子类的方式类实现代理,这种方法就叫做:Cglib代理
 *      1.需要引入cglib的jar文件,但是Spring的核心包中已经包括了Cglib功能,所以直接引入spring-core-3.2.5.jar即可.
 *      2.引入功能包后,就可以在内存中动态构建子类
 *      3.代理的类不能为final,否则报错
 *      4.目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.
 *
 *
 * 注：注意区分代理对象和代理类
 *
 *  一般都是获取代理对象，如何获取代理类呢？
 *
 *
 */
public class Test {

    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        UserDao userDao = new UserDao();
        Enhancer enhancer = new Enhancer();
        enhancer.setCallbackType(Interceptor.class);
        enhancer.setSuperclass(userDao.getClass());
        Class aClass = enhancer.createClass();
        Enhancer.registerCallbacks(aClass,new Callback[]{new Interceptor()});
        UserDao userDaoProxy = (UserDao) aClass.newInstance();
//        注意有参构造器创建对象
//        Constructor constructor = aClass.getConstructor(String.class);
//        Object o = constructor.newInstance("");
        userDaoProxy.save();

    }



    private static class Interceptor implements MethodInterceptor{

        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//            System.out.println("Object:"+o);
//            System.out.println("objects:"+objects);
//            System.out.println("methodProxy:"+methodProxy);
//            System.out.println("method:"+method);
            System.out.println("被代理了。。。。");
            Object invoke = methodProxy.invokeSuper(o, objects);
            return invoke;
        }
    }
}
